package com.qiangesoft.pdf.util;

import com.alibaba.fastjson.JSONObject;
import org.springframework.util.CollectionUtils;

import java.io.IOException;
import java.util.*;

/**
 * pdf规则数据分析工具类
 * ps:分析处理PdfUtil解决不了的表格，没有格子
 *
 * @author qiangesoft
 * @date 2025-05-28
 */
public class PdfRuleDataUtil {

    public static void main(String[] args) throws IOException {
        String fileTxt = PdfUtil.readTxtFromPdf("C:\\Users\\admin\\Desktop\\流水文件\\中国建设银行.pdf", null);
        System.out.println(readTxt(fileTxt, "卡号/账号:", "客户名称：").trim());
        System.out.println(readTxt(fileTxt, "客户名称：", "起始日期：").trim());
        System.out.println(readTxt(fileTxt, "起始日期：", "结束日期：").trim());
        System.out.println(readTxt(fileTxt, "结束日期：", "序号").trim());
        List<Map<String, String>> dataList = readTableData(fileTxt, "序号 摘要 币别 钞汇 交易日期 交易金额 账户余额 交易地点/附言 对方账号与户名", "生成时间:");
        for (Map<String, String> map : dataList) {
            System.out.println(JSONObject.toJSONString(map));
        }
    }

    /**
     * 解析文本
     *
     * @param fileTxt
     * @param startStr
     * @param endStr
     * @return
     */
    public static String readTxt(String fileTxt, String startStr, String endStr) {
        return PdfUtil.readTxtFormTxt(fileTxt, startStr, endStr);
    }

    /**
     * 解析表格数据
     *
     * @param fileTxt 文本数据
     * @param startStr 开始字符串 【一般为标题行，字段根据标题行定，***很重要***】
     * @param endStr 结束字符串 【结束标志，如果表格连续中间没有重复的标题行则直接使用表格末尾的结束标志即可，如果表格不连续每页都有标题行则使用每页的结束标志】
     * @return
     */
    public static List<Map<String, String>> readTableData(String fileTxt, String startStr, String endStr) {
        int length = startStr.trim().split(" ").length;
        List<String> fieldList = new ArrayList<>();
        for (int i = 1; i <= length; i++) {
            fieldList.add("k" + i);
        }

        List<Map<String, String>> lists = new ArrayList<>();
        while (true) {
            String dataStr = readTxt(fileTxt, startStr, endStr);
            if (dataStr == null) {
                break;
            }
            List<Map<String, String>> pageLists = readDataFromTxt(dataStr, startStr, fieldList);
            fileTxt = fileTxt.substring(fileTxt.indexOf(endStr) + endStr.length());
            if (CollectionUtils.isEmpty(pageLists)) {
                break;
            } else {
                lists.addAll(pageLists);
            }
        }

        return lists;
    }

    /**
     * 解析pdf的文本数据
     * ps:通过换行符进行分割行，然后根据空格分割列【如果列中数据存在空格则无法解决】
     *
     * @param dataStr 待解析的文本
     * @param tableHeadTxt 标题行文本
     * @param fieldList 字段列表
     * @return
     */
    private static List<Map<String, String>> readDataFromTxt(String dataStr, String tableHeadTxt, List<String> fieldList) {
        List<Map<String, String>> dataList = new ArrayList<>();

        int cellNum = fieldList.size();
        // "\r\n" or "\n"
        String[] split = dataStr.split(System.lineSeparator());

        StringBuilder chargeStr = new StringBuilder();
        for (int a = 0; a < split.length; a++) {
            String itemStr = split[a];
            // 标题行跳过
            if (itemStr.contains(tableHeadTxt)) {
                continue;
            }

            String[] split1;
            if (!chargeStr.toString().isEmpty()) {
                // 上一行未处理【加上本行一起处理】
                chargeStr.append(itemStr);
                split1 = chargeStr.toString().split(" ");
            } else {
                split1 = itemStr.split(" ");
            }

            if (split1.length < cellNum) { // 不足列数
                // 拼接本行
                if (chargeStr.toString().isEmpty()) {
                    chargeStr.append(itemStr);
                }
                // 最后一行特殊处理
                if (a == split.length - 1) {
                    Map<String, String> dataMap = new HashMap<>();
                    for (int i = 0; i < cellNum; i++) {
                        if (i > split1.length - 1) {
                            dataMap.put(fieldList.get(i), null);
                        } else {
                            dataMap.put(fieldList.get(i), split1[i]);
                        }
                    }
                    dataList.add(dataMap);
                }
            } else if (split1.length > cellNum) { // 超过列数
                if (!chargeStr.toString().isEmpty()) {
                    // 处理上一行
                    String[] split2 = chargeStr.toString().replace(itemStr, "").split(" ");
                    Map<String, String> dataMap = new HashMap<>();
                    for (int i = 0; i < cellNum; i++) {
                        if (i > split2.length - 1) {
                            dataMap.put(fieldList.get(i), null);
                        } else {
                            dataMap.put(fieldList.get(i), split2[i]);
                        }
                    }
                    dataList.add(dataMap);
                }

                // 处理本行
                chargeStr = new StringBuilder();
                String[] split3 = itemStr.split(" ");
                if (split3.length < cellNum) { // 本行不足列数
                    // 拼接本行
                    if (chargeStr.toString().isEmpty()) {
                        chargeStr.append(itemStr);
                    }
                    // 最后一行特殊处理
                    if (a == split.length - 1) {
                        Map<String, String> dataMap = new HashMap<>();
                        for (int i = 0; i < cellNum; i++) {
                            if (i > split3.length - 1) {
                                dataMap.put(fieldList.get(i), null);
                            } else {
                                dataMap.put(fieldList.get(i), split3[i]);
                            }
                        }
                        dataList.add(dataMap);
                    }
                } else { // 本行大于等于列数
                    Map<String, String> dataMap = new HashMap<>();
                    for (int i = 0; i < cellNum; i++) {
                        if (i > split3.length - 1) {
                            dataMap.put(fieldList.get(i), null);
                        } else {
                            dataMap.put(fieldList.get(i), split3[i]);
                        }
                    }
                    dataList.add(dataMap);
                }
            } else { // 等于列数
                Map<String, String> dataMap = new HashMap<>();
                for (int i = 0; i < cellNum; i++) {
                    dataMap.put(fieldList.get(i), split1[i]);
                }
                dataList.add(dataMap);
                chargeStr = new StringBuilder();
            }
        }

        return dataList;
    }


}
